package com.xinqi.modules.course.content.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.xinqi.common.base.enums.YesNoEnum;
import com.xinqi.common.base.enums.YesNoNumberEnum;
import com.xinqi.common.base.error.CommonErrors;
import com.xinqi.common.base.response.PageInfo;
import com.xinqi.common.base.response.Param;
import com.xinqi.common.base.response.R;
import com.xinqi.common.core.enums.AssistantMessageTypeEnum;
import com.xinqi.common.core.enums.CourseContentTypeEnum;
import com.xinqi.common.core.enums.ResultConfigEnum;
import com.xinqi.common.core.utils.MessageUtils;
import com.xinqi.common.mybatis.data.service.impl.BaseServiceImpl;
import com.xinqi.common.mybatis.utils.Pages;
import com.xinqi.common.mybatis.utils.Queries;
import com.xinqi.common.satoken.utils.LoginHelper;
import com.xinqi.modules.course.chapter.domain.CourseChapterEntity;
import com.xinqi.modules.course.chapter.mapper.CourseChapterMapper;
import com.xinqi.modules.course.classmenu.service.ClassMenuService;
import com.xinqi.modules.course.clazz.domain.ClassStudentEntity;
import com.xinqi.modules.course.clazz.dto.rsp.ClassStudentResultDTO;
import com.xinqi.modules.course.clazz.service.ClassStudentService;
import com.xinqi.modules.course.content.convert.CourseContentConvert;
import com.xinqi.modules.course.content.domain.CourseContentEntity;
import com.xinqi.modules.course.content.dto.req.*;
import com.xinqi.modules.course.content.dto.rsp.CourseContentResultDTO;
import com.xinqi.modules.course.content.dto.rsp.CourseRepeatContentResult;
import com.xinqi.modules.course.content.mapper.CourseContentMapper;
import com.xinqi.modules.course.content.service.CourseContentService;
import com.xinqi.modules.databank.client.CourseResourceClient;
import com.xinqi.modules.databank.dto.req.CourseResourceUpdateDTO;
import com.xinqi.modules.discuss.discuss.client.CourseDiscussClient;
import com.xinqi.modules.discuss.discuss.dto.req.CourseDiscussUpdateDTO;
import com.xinqi.modules.exam.paper.client.CourseExamPaperClient;
import com.xinqi.modules.exam.paper.dto.req.CourseExamPaperUpdateDTO;
import com.xinqi.modules.homework.homework.client.CourseHomeworkClient;
import com.xinqi.modules.homework.homework.dto.req.CourseHomeworkStudentDetailDTO;
import com.xinqi.modules.homework.homework.dto.req.CourseHomeworkUpdateDTO;
import com.xinqi.modules.homework.homework.dto.rsp.CourseHomeworkResultDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 课程内容表服务层实现
 *
 * @author: system
 * @date: 2023/03/08
 */
@Service("courseContentService")
@RequiredArgsConstructor
public class CourseContentServiceImpl extends BaseServiceImpl<CourseContentMapper, CourseContentEntity> implements CourseContentService {

    private final CourseContentConvert courseContentConvert;

    private final CourseChapterMapper courseChapterMapper;
    private final ClassStudentService classStudentService;

    private final ClassMenuService classMenuService;

    private final CourseHomeworkClient courseHomeworkClient;
    private final CourseDiscussClient courseDiscussClient;

    private final CourseExamPaperClient courseExamPaperClient;

    private final CourseResourceClient courseResourceClient;


    /**
     * 分页查询 课程内容表数据
     */
    @Override
    @DS("slaver")
    public PageInfo<CourseContentResultDTO> page(Param pageable, CourseContentQueryDTO query) {
        List<String> orderList = new ArrayList<>();
        orderList.add("sort,desc");
        orderList.add("release_time,desc");
        pageable.setSorts(orderList);
        pageable.setPageSize(20L);
        return this.baseMapper.selectDtoPageInfo(Pages.page(pageable), wrapper(query), courseContentConvert::convert);
    }

    /**
     * 查询 课程内容根据课程信息
     */
    @Override
    public List<CourseContentResultDTO> findByContent(CourseContentQueryDTO query) {
        LambdaQueryWrapper<CourseContentEntity> wrapper = Queries.lambda();
        Queries.accept(query.getClassId(), v -> wrapper.eq(CourseContentEntity::getClassId, v));
        Queries.accept(query.getContentId(), v -> wrapper.eq(CourseContentEntity::getContentId, v));
        Queries.accept(query.getType(), v -> wrapper.eq(CourseContentEntity::getType, v));
        return this.baseMapper.selectDtoList(wrapper, courseContentConvert::convert);
    }

    /**
     * 查询 课程内容表数据
     */
    @Override
    public List<CourseContentResultDTO> find(CourseContentQueryDTO query) {
        return this.baseMapper.selectDtoList(wrapper(query), courseContentConvert::convert);
    }

    private LambdaQueryWrapper<CourseContentEntity> wrapper(CourseContentQueryDTO query) {
        LambdaQueryWrapper<CourseContentEntity> wrapper = new LambdaQueryWrapper();
        wrapper.eq(CourseContentEntity::getContentId, query.getContentId());
        wrapper.eq(CourseContentEntity::getClassId, query.getClassId());
        wrapper.eq(CourseContentEntity::getType, query.getType());
        wrapper.eq(CourseContentEntity::getStatus, YesNoNumberEnum.YES.getCode());
        return wrapper;
    }

    /**
     * 根据id查询 课程内容表数据
     */
    @Override
    public CourseContentResultDTO findById(Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        return this.baseMapper.selectDtoById(id, courseContentConvert::convert);
    }

    /**
     * 新增 课程内容表数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R insertOrUpdate(CourseContentCreateDTO dto) {
        CourseContentQueryDTO queryDTO = new CourseContentQueryDTO();
        queryDTO.setClassId(dto.getClassId());
        queryDTO.setContentId(dto.getContentId());
        List<CourseContentResultDTO> oldList = this.findByContent(queryDTO);
        if (oldList == null || oldList.isEmpty()) {
            CourseContentEntity entity = courseContentConvert.create(dto);
            this.save(entity);
        } else {
            CommonErrors.INTERNAL_SERVER_ERROR.check(oldList.size() == 1, "数据获取到多条");
            CourseContentEntity entity = courseContentConvert.create(dto);
            entity.setId(oldList.get(0).getId());
            this.updateById(entity);
        }
        return R.ok(ResultConfigEnum.ADD_OK.getDescription());
    }

    /**
     * 根据id修改 课程内容表数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R updateById(CourseContentUpdateDTO dto) {
        CourseContentEntity old = Optional.ofNullable(this.getById(dto.getId()))
            .orElseThrow(() -> CommonErrors.BAD_REQUEST.asException(ResultConfigEnum.DATA_NOT_EXIST.getDescription()));
        CourseContentEntity entity = courseContentConvert.update(dto);
        this.updateById(entity);
        return R.ok(ResultConfigEnum.UPDATE_OK.getDescription());
    }

    /**
     * 根据id删除 课程内容表数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R deleteById(Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        this.removeById(id);
        return R.ok(ResultConfigEnum.DELETE_OK.getDescription());
    }


    /**
     * 课程栏目移动到章节
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R shiftIn(List<CourseContentUpdateDTO> list) {
        for (CourseContentUpdateDTO dto : list) {
            CommonErrors.BAD_REQUEST.check(Objects.nonNull(dto.getClassId()), "班级ID不能为空");
            CommonErrors.BAD_REQUEST.check(Objects.nonNull(dto.getContentId()), "课程内容ID不能为空");
            CommonErrors.BAD_REQUEST.check(Objects.nonNull(dto.getType()), "课程内容类型不能为空");
            CourseContentQueryDTO queryDTO = new CourseContentQueryDTO();
            queryDTO.setClassId(dto.getClassId());
            queryDTO.setContentId(dto.getContentId());
            queryDTO.setType(dto.getType());
            List<CourseContentResultDTO> resultDTOS = find(queryDTO);

            // 防止多数据异常问题此处判断数据是否存在且唯一
            if (resultDTOS != null && resultDTOS.size() == 1) {
                dto.setId(resultDTOS.get(0).getId());
                this.updateById(dto);
            }
            // 更新作业章节信息
            if (Objects.equals(CourseContentTypeEnum.HOMEWORK.getCode(), dto.getType())) {
                CourseHomeworkResultDTO courseHomeworkResultDTO = R.as(courseHomeworkClient.findById(dto.getContentId(), new CourseHomeworkStudentDetailDTO()));
                if (Objects.nonNull(courseHomeworkResultDTO)) {
                    CourseHomeworkUpdateDTO updateDTO = new CourseHomeworkUpdateDTO();
                    updateDTO.setId(courseHomeworkResultDTO.getId());
                    updateDTO.setChapterId(dto.getChapterId());

                    courseHomeworkClient.update(courseHomeworkResultDTO.getId(), updateDTO);
                }
            }
            // 更新讨论章节信息
            else if (Objects.equals(CourseContentTypeEnum.DISCUSS.getCode(), dto.getType())) {
                CourseDiscussUpdateDTO updateDTO = new CourseDiscussUpdateDTO();
                updateDTO.setId(dto.getContentId());
                updateDTO.setChapterId(dto.getChapterId());
                courseDiscussClient.update(dto.getContentId(), updateDTO);
            }
            //更新测评章节信息
            else if (Objects.equals(CourseContentTypeEnum.EXAM.getCode(), dto.getType())) {
                CourseExamPaperUpdateDTO updateDTO = new CourseExamPaperUpdateDTO();
                updateDTO.setId(dto.getContentId());
                updateDTO.setChapterId(dto.getChapterId());
                courseExamPaperClient.update(dto.getContentId(), updateDTO);
            }
            //更新资料库章节信息
            else if (Objects.equals(CourseContentTypeEnum.INTERACTIVE_VIDEO.getCode(), dto.getType())
                || Objects.equals(CourseContentTypeEnum.COURSEWARE.getCode(), dto.getType())
                || Objects.equals(CourseContentTypeEnum.DATA.getCode(), dto.getType())) {

                CourseResourceUpdateDTO updateDTO = new CourseResourceUpdateDTO();
                updateDTO.setId(dto.getContentId());
                updateDTO.setChapterId(dto.getChapterId());
                courseResourceClient.update(dto.getContentId(), updateDTO);
            }
        }
        return R.ok("移动成功");
    }

    /**
     * 课程栏目移出章节
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R shiftOut(List<CourseContentUpdateDTO> list) {
        for (CourseContentUpdateDTO dto : list) {
            CommonErrors.BAD_REQUEST.check(Objects.nonNull(dto.getClassId()), "班级ID不能为空");
            CommonErrors.BAD_REQUEST.check(Objects.nonNull(dto.getContentId()), "课程内容ID不能为空");
            CommonErrors.BAD_REQUEST.check(Objects.nonNull(dto.getType()), "课程内容类型不能为空");
            CourseContentQueryDTO queryDTO = new CourseContentQueryDTO();
            queryDTO.setClassId(dto.getClassId());
            queryDTO.setContentId(dto.getContentId());
            queryDTO.setType(dto.getType());
            List<CourseContentResultDTO> resultDTOS = find(queryDTO);
            // 防止多数据异常问题此处判断数据是否存在且唯一
            if (resultDTOS != null && resultDTOS.size() == 1) {
                dto.setId(resultDTOS.get(0).getId());
                dto.setChapterId(0L);
                this.updateById(dto);
            }
            // 更新作业章节信息
            if (dto.getType().equals(CourseContentTypeEnum.HOMEWORK.getCode())) {
                CourseHomeworkUpdateDTO updateDTO = new CourseHomeworkUpdateDTO();
                updateDTO.setId(dto.getContentId());
                updateDTO.setChapterId(dto.getChapterId());
            }
            // 更新讨论章节信息
            if (Objects.equals(CourseContentTypeEnum.DISCUSS.getCode(), dto.getType())) {
                CourseDiscussUpdateDTO updateDTO = new CourseDiscussUpdateDTO();
                updateDTO.setId(dto.getContentId());
                updateDTO.setChapterId(dto.getChapterId());
                courseDiscussClient.update(dto.getContentId(), updateDTO);
            }
            //更新测评章节信息
            if (Objects.equals(CourseContentTypeEnum.EXAM.getCode(), dto.getType())) {
                CourseExamPaperUpdateDTO updateDTO = new CourseExamPaperUpdateDTO();
                updateDTO.setId(dto.getContentId());
                updateDTO.setChapterId(dto.getChapterId());
                courseExamPaperClient.update(dto.getContentId(), updateDTO);
            }
            //更新互动视频章节信息
            if (Objects.equals(CourseContentTypeEnum.INTERACTIVE_VIDEO.getCode(), dto.getType())
                || Objects.equals(CourseContentTypeEnum.COURSEWARE.getCode(), dto.getType())
                || Objects.equals(CourseContentTypeEnum.DATA.getCode(), dto.getType())) {
                CourseResourceUpdateDTO updateDTO = new CourseResourceUpdateDTO();
                updateDTO.setId(dto.getContentId());
                updateDTO.setChapterId(dto.getChapterId());
                courseResourceClient.update(dto.getContentId(), updateDTO);
            }
        }
        return R.ok("移出成功");
    }

    @Override
    @DS("slaver")
    public PageInfo<Map<String, Object>> selectYearMonth(Param pageable, Long classId) {
        Page<Map<String, Object>> page = new Page<>(pageable.getPageNum(), pageable.getPageSize());
        IPage<Map<String, Object>> res = this.baseMapper.selectYearMonth(page, classId);
        return Pages.convert(res);
    }

    /**
     * 课程汇总年月日周查询
     */
    @Override
    @DS("slaver")
    public PageInfo<Map<String, Object>> selectYearMonthDay(Param pageable, Long classId) {
        Page<Map<String, Object>> page = new Page<>(pageable.getPageNum(), pageable.getPageSize());

        // 获取隐藏板块
        List<Integer> contentTypes = classMenuService.checkContentByMenu(classId);
        if (CollectionUtils.isEmpty(contentTypes)) {
            contentTypes.add(0);
        }

        IPage<Map<String, Object>> res = this.baseMapper.selectYearMonthDay(page, classId, contentTypes);
        return Pages.convert(res);
    }

    @Override
    public List<Map<String, Object>> selectMonthDay(ContentMonthDayQueryDTO queryParam) {
        List<Map<String, Object>> res = this.baseMapper.selectMonthDay(queryParam);
        return res;
    }

    @Override
    public List<CourseRepeatContentResult> selectAllDay(ContentMonthDayQueryDTO queryParam) {
        Long userId = LoginHelper.getUserId();
        ClassStudentEntity entity = classStudentService.selectByClassIdAndStudentId(queryParam.getClassId(), userId);

        // 获取隐藏板块
        List<Integer> contentTypes = classMenuService.checkContentByMenu(queryParam.getClassId());
        if (CollectionUtils.isNotEmpty(contentTypes)) {
            // 存在显示赋值存在的板块
            queryParam.setContentTypes(contentTypes);
        } else {
            // 没有则传0没有板块
            contentTypes.add(0);
        }

        // 判断是老师还是学生，根据角色查询不同的内容（作业）
        List<CourseRepeatContentResult> list = new ArrayList<>();
        if (entity != null) {
            if (entity.getIsTeacher().equals(Integer.parseInt(YesNoEnum.YES.getCode()))) {
                //是老师
                list = this.baseMapper.selectTeacherAllDay(queryParam);
            } else {
                //是学生,获取主学生
                ClassStudentResultDTO masterStudent = classStudentService.findVirtualClassStudentByClassIdAndUserId(queryParam.getClassId(), userId);
                queryParam.setStudentId(masterStudent.getStudentId());
                list = this.baseMapper.selectStudentAllDay(queryParam);
            }
        }
        return list;
    }

    @Override
    public CourseContentEntity selectByContentIdAndType(Long contentId, Integer type) {
        LambdaQueryWrapper<CourseContentEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CourseContentEntity::getContentId, contentId)
            .eq(CourseContentEntity::getType, type);
        return this.getOne(wrapper);
    }

    /**
     * 同步删除co_course_content中的互动视频数据
     *
     * @param contentId
     * @return
     */
    @Override
    public Boolean deleteVideoById(Long contentId) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(contentId), "互动视频ID不能为空");
        CourseContentEntity entity = this.selectByContentIdAndType(contentId, 6);
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(entity), "数据不存在");
        this.removeById(entity.getId());
        return SqlHelper.retBool(getBaseMapper().deleteById(entity.getId()));
    }

    @Override
    public List<CourseContentEntity> getCourseContentByChapterId(Long chapterId) {

        // 添加权限判断
        Long userId = LoginHelper.getUserId();
        CourseChapterEntity chapterEntity = this.courseChapterMapper.selectById(chapterId);

        CourseContentQueryByChapterDTO chapterDTO = new CourseContentQueryByChapterDTO();
        chapterDTO.setChapterId(chapterId);

        // 隐藏板块判断
        List<Integer> contentTypes = classMenuService.checkContentByMenu(chapterEntity.getClassId());
        if (CollectionUtils.isNotEmpty(contentTypes)) {
            chapterDTO.setContentTypes(contentTypes);
        } else {
            // 没有则传0没有板块
            contentTypes.add(0);
            chapterDTO.setContentTypes(contentTypes);
        }

        ClassStudentResultDTO mainStudent = classStudentService.findVirtualClassStudentByClassIdAndUserId(chapterEntity.getClassId(), userId);
        // 判断是老师还是学生，根据角色查询不同的内容（作业）
        List<CourseContentEntity> list = new ArrayList<>();
        if (Objects.nonNull(mainStudent)) {
            //是学生
            chapterDTO.setStudentId(mainStudent.getStudentId());
            list = this.baseMapper.selectStudentContentByChapterId(chapterDTO);
        } else {
            //是老师
            list = this.baseMapper.selectTeacherContentByChapterId(chapterDTO);
        }
        return list;
    }

    /**
     * 根据课程内容ID和类型删除内容
     */
    @Override
    public Boolean deleteCourseContentById(List<Long> contentIds, Integer type) {
        return this.baseMapper.deleteByCourseContent(contentIds, type) > 0;
    }

    /**
     * 根据课程内容ID和类型更新内容
     */
    @Override
    public Boolean updateCourseContentByType(List<CourseContentEntity> list) {
        return this.baseMapper.updateCourseContentByType(list);
    }

    @Override
    public void removeCourseContentBatchByContentId(List<Long> idList) {
        this.baseMapper.removeCourseContentBatchByContentId(idList);
    }

    /**
     * 校验课程内容是否存在
     */
    @Override
    public boolean checkCourseContent(Integer type, Long contentId) {
        CourseContentEntity entity = this.selectByContentIdAndType(contentId, type);
        return Objects.nonNull(entity);
    }

    @Override
    public int deleteExamById(Long id) {
        return this.baseMapper.deleteOutById(id);
    }

    /**
     * 校验课程内容是否已删除
     *
     * @param contentId 课程内容ID
     * @param type      课程内容类型
     */
    @Override
    public void exitCourseContent(Long contentId, Integer type) {
        if (Objects.equals(AssistantMessageTypeEnum.COURSEWARE.getType(), type) || Objects.equals(AssistantMessageTypeEnum.DATA.getType(), type)
            || Objects.equals(AssistantMessageTypeEnum.INTERACTIVE_VIDEO.getType(), type)) {
            CourseContentEntity resource = this.selectByContentIdAndType(contentId, type);
            if (Objects.equals(AssistantMessageTypeEnum.COURSEWARE.getType(), type)) {
                CommonErrors.NOT_DATA.check(Objects.nonNull(resource), MessageUtils.message("course.resource.courseware.id.not.exit"));
            } else if (Objects.equals(AssistantMessageTypeEnum.DATA.getType(), type)) {
                CommonErrors.NOT_DATA.check(Objects.nonNull(resource), MessageUtils.message("course.resource.data.id.not.exit"));
            } else {
                CommonErrors.NOT_DATA.check(Objects.nonNull(resource), MessageUtils.message("course.resource.video.id.not.exit"));
            }
        } else if (Objects.equals(AssistantMessageTypeEnum.HOMEWORK.getType(), type)) {
            CourseContentEntity homework = this.selectByContentIdAndType(contentId, type);
            CommonErrors.NOT_DATA.check(Objects.nonNull(homework), MessageUtils.message("course.homework.id.not.exit"));
        } else if (Objects.equals(AssistantMessageTypeEnum.EXAM.getType(), type)) {
            CourseContentEntity exam = this.selectByContentIdAndType(contentId, type);
            CommonErrors.NOT_DATA.check(Objects.nonNull(exam), MessageUtils.message("course.exam.id.not.exit"));
        } else if (Objects.equals(AssistantMessageTypeEnum.DISCUSS.getType(), type)) {
            CourseContentEntity discuss = this.selectByContentIdAndType(contentId, type);
            CommonErrors.NOT_DATA.check(Objects.nonNull(discuss), MessageUtils.message("course.discuss.is.remove"));
        } else if (Objects.equals(AssistantMessageTypeEnum.NOTICE.getType(), type)) {
            CourseContentEntity notice = this.selectByContentIdAndType(contentId, type);
            CommonErrors.NOT_DATA.check(Objects.nonNull(notice), MessageUtils.message("course.notice.is.remove"));
        }
    }

}
